package com.ouc.dataMange.controller;

import com.ouc.common.annotation.Log;
import com.ouc.common.config.B504Config;
import com.ouc.common.config.NcConfig;
import com.ouc.common.config.OUCAjaxResult;
import com.ouc.common.config.properties.ApplicationProperties;
import com.ouc.common.core.domain.AjaxResult;
import com.ouc.common.core.page.TableDataInfo;
import com.ouc.common.enums.BusinessType;
import com.ouc.common.utils.DateUtils;
import com.ouc.common.utils.StringUtils;
import com.ouc.common.utils.file.FileUtils;
import com.ouc.common.utils.poi.ExcelUtil;
import com.ouc.dataMange.domain.SysDiskSpace;
import com.ouc.dataMange.domain.SysUploadFile;
import com.ouc.dataMange.domain.Upload;
import com.ouc.dataMange.service.*;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.*;

import static com.ouc.common.constant.NcConstants.COPERNICUS;
import static com.ouc.common.constant.NcConstants.LEVEL_DEPTH;
import static com.ouc.common.utils.SecurityUtils.getUserId;


/**
 * 上传文件Controller
 *
 * @author b504
 * @date 2022-09-18
 */
@Controller
@RestController
@CrossOrigin
@RequestMapping("/fileManage/atmosphere")
public class AtmosphereController extends BaseController {

  private String prefix = "dataManage/fileMange/atmosphere";

  @Autowired
  private AtmosphereService uploadService;

  @Autowired
  NcConfig ncConfig;

  @Autowired
  ApplicationProperties applicationProperties;

  @Autowired
  NcUploadService ncUploadService;

  @Autowired
  B504Config b504Config;

  @Autowired
  private ISysUploadFileService sysUploadFileService;

  @Autowired
  private ISysDataSetService sysDataSetService;

  @Autowired
  private ISysMemoryDeviceService sysMemoryDeviceService;


//
//  @Autowired
//  ServerConfig serverConfig;

  //  @RequiresPermissions("fileManage:upload:view")
  @GetMapping()
  public String ncUpload() {
    return prefix + "/upload";
  }


  /**
   * 查询上传文件列表（nc海洋环境数据）
   */
//  @RequiresPermissions("fileManage:upload:list")
  @PostMapping("/list")
  @ResponseBody
  public TableDataInfo list(Upload upload) {
    startPage();
    List<Upload> list = uploadService.selectUploadList(upload);
    return getDataTable(list);
  }

  /**
   * 导出上传文件列表
   */
//  @RequiresPermissions("fileManage:upload:export")
  @Log(title = "上传文件", businessType = BusinessType.EXPORT)
  @PostMapping("/export")
  @ResponseBody
  public AjaxResult export(Upload upload) {
    List<Upload> list = uploadService.selectUploadList(upload);
    ExcelUtil<Upload> util = new ExcelUtil<>(Upload.class);
    return util.exportExcel(list, "上传文件数据");
  }

  /**
   * 新增上传文件
   */
  @GetMapping("/add")
  public AjaxResult add(Upload upload) {
    return toAjax(uploadService.insertUpload(upload));
  }

  /**
   * 新增保存文件管理
   */
//  @RequiresPermissions("fileManage:upload:add")
  @Log(title = "文件管理", businessType = BusinessType.INSERT)
  @PostMapping("/add")
  @ResponseBody
  public AjaxResult addSave(Upload upload) {
    upload.setUserId(getUserId().intValue());
    return toAjax(uploadService.insertUpload(upload));
  }

  /**
   * 修改文件管理
   */
//  @RequiresPermissions("fileManage:upload:edit")
  @ResponseBody
  @RequestMapping("/update")
  public AjaxResult update(Upload upload) {
    return toAjax(uploadService.updateUpload(upload));
  }

  /**
   * 查询详细信息
   *
   * @param fileId
   * @return
   */
  @GetMapping(value = "/{fileId}")
  public AjaxResult getInfo(@PathVariable("fileId") Integer fileId) {
    return success(uploadService.selectUploadByFileId(fileId));
  }

  /**
   * 修改保存上传文件
   */
//  @RequiresPermissions("fileManage:upload:edit")
  @Log(title = "上传文件", businessType = BusinessType.UPDATE)
  @PostMapping("/edit")
  @ResponseBody
  public AjaxResult editSave(Upload upload) {
    return toAjax(uploadService.updateUpload(upload));
  }

  /**
   * 删除
   *
   * @param fileIds
   * @return
   */
  @DeleteMapping("/{fileIds}")
  public AjaxResult remove(@PathVariable Integer[] fileIds) {
    return toAjax(uploadService.deleteUploadByFileIds(fileIds));
  }

  /**
   * 删除文件管理
   */
//  @RequiresPermissions("fileManage:upload:remove")
  @Log(title = "文件管理", businessType = BusinessType.DELETE)
  @PostMapping("/remove")
  @ResponseBody
  public AjaxResult remove(@RequestParam(value = "fileIds") String ids) {
    try {
      /*如果是多条记录，前台会传字符串用','分割
       * 后台使用逗号切分循环删除*/
      if (ids.contains(",")) {
        String[] split = ids.split(",");
        for (String s : split) {
          Upload upload = uploadService.selectUploadByFileId(Integer.valueOf(s));
          if (getFilePath(upload) != null) {
            File file = new File(getFilePath(upload));
            if (file.exists() && file.isFile()) {
              org.apache.commons.io.FileUtils.delete(file);
              logger.info("已删除:{}", file.getCanonicalPath());
            }
          }
        }
      } else {
        Upload upload = uploadService.selectUploadByFileId(Integer.valueOf(ids));
        if (getFilePath(upload) != null) {
          File file = new File(getFilePath(upload));
          if (file.exists() && file.isFile()) {
            org.apache.commons.io.FileUtils.delete(file);
          }
        }
      }
      return toAjax(uploadService.deleteUploadByFileIds(ids));
    } catch (Exception e) {
      e.printStackTrace();
      logger.error("删除失败由于{}", e.getMessage());
      return AjaxResult.error("删除失败由于" + e.getMessage());
    }
  }


  /**
   * 上传整个文件夹
   *
   * @param file 文件
   * @return
   */
////  @RequiresPermissions("fileManage:upload:remove")
  @ResponseBody
  @RequestMapping("/uploadMultiFile")
  @Log(title = "上传大气文件", businessType = BusinessType.OTHER, isSaveRequestData = false)
  public AjaxResult uploadMultiFile(MultipartFile[] file,
                                    @RequestParam(value = "userName", required = false, defaultValue = "中国海洋大学") String userName,
                                    @RequestParam(value = "userId", required = false, defaultValue = "1") Integer userId,
                                    @RequestParam(value = "dataSetId", required = false, defaultValue = "9") Integer dataSetId,
                                    @RequestParam(value = "memoryId", required = false, defaultValue = "12") Integer memoryId,
                                    @RequestParam(value = "ifPng", required = false, defaultValue = "0") Integer ifPng) {
    return uploadFile(userId, userName, file, dataSetId, memoryId, ifPng);
  }


  @ResponseBody
  @RequestMapping("/test")
  //@Log(title = "上传哥白尼文件", businessType = BusinessType.OTHER, isSaveRequestData = false)
  public AjaxResult test() {
    return AjaxResult.success("testSuccess");
  }

  /**
   * 上传多个文件
   *
   * @param file 文件
   * @return
   */
  @ResponseBody
  @RequestMapping("/uploadMultiFileByOrigin")
  @Log(title = "上传ERA5文件", businessType = BusinessType.OTHER, isSaveRequestData = false)
  public AjaxResult uploadMultiFileByOrigin(MultipartFile[] file) {
    return uploadFile(null, null, file, null, null, null);
  }

  /**
   * 上传弹窗
   *
   * @return
   */
  @RequestMapping("/uploadMessage")
  public String getUploadMessage() {
    return prefix + "/uploadMessage";
  }

  /**
   * nc文件下载使用流的方式进行下载
   *
   * @param response 返回请求
   * @param fileId   文件的id
   */
  @RequestMapping("/download")
  @Log(title = "下载nc文件", businessType = BusinessType.EXPORT)
  @ResponseBody
  public void getDownload(HttpServletResponse response, @RequestParam("fileId") Integer fileId) {
    try {
      Upload upload = uploadService.selectUploadByFileId(fileId);
      String filePath = sysMemoryDeviceService.selectSysMemoryDeviceById(upload.getFileMemoryId()).getSysMemoryDevice()
          + sysDataSetService.selectSysDataSetById(upload.getFileDataSetId()).getDataSetDevice() + upload.getFilePath();
      InputStream is = new FileInputStream(filePath);
      byte[] data = IOUtils.toByteArray(is);
//      response.reset();
      String fileName = "attachment; filename=\"";
      Date fileTime = upload.getFileTime();
      SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");

      fileName = fileName + sdf.format(fileTime) + ".nc\"";

      response.setHeader("Content-Disposition", fileName);
      response.addHeader("Content-Length", "" + data.length);
      response.setContentType("application/octet-stream; charset=UTF-8");
      IOUtils.write(data, response.getOutputStream());
    } catch (Exception e) {
      e.printStackTrace();
    }

  }


  /**
   * 通过查询条件从数据库中查询
   * variableList前台传递带“，”的字符串
   * 后台要进行处理
   *
   * @param upload 查询条件
   * @return
   */
  @RequestMapping(value = "selectFactorList")
  @ResponseBody
  public TableDataInfo selectFactorList(Upload upload) {
    String variableList = "";
    if (upload.getVariableList().contains(",")) {
      variableList = upload.getVariableList().substring(0, upload.getVariableList().indexOf(","));
    }
    upload.setVariableList(variableList);
    startPage();
    List<Upload> list = uploadService.selectFactorList(upload);
    return getDataTable(list);
  }

  /**
   * 通过查询条件从数据库中查询
   * variableList前台传递带“，”的字符串
   * 后台要进行处理
   *
   * @param upload 查询条件
   * @return
   */
  @RequestMapping(value = "selectFilePathList")
  @ResponseBody
  public TableDataInfo selectFilePathList(Upload upload) {
    startPage();
    List<Upload> list = uploadService.selectFactorList(upload);
    for (Upload upload1 : list) {
      String filePath = getFilePath(upload1);
      upload1.setFilePath(filePath);
      Map<String, Object> params = new HashMap<>();
      params.put("fileName", FileUtils.getName(filePath));
      upload1.setParams(params);
    }
    return getDataTable(list);
  }

  /**
   * 通过查询条件返回前台
   * 对于结果的处理，将深度层级转化为米数
   *
   * @param upload
   * @return
   */
  @RequestMapping(value = "selectFactorListForDepth")
  @ResponseBody
  public TableDataInfo selectFactorListForDepth(Upload upload) {
    String variableList = "";
    if (upload.getVariableList().contains(",")) {
      variableList = upload.getVariableList().substring(0, upload.getVariableList().indexOf(","));
    }
    upload.setVariableList(variableList);
    startPage();
    List<Upload> list = uploadService.selectFactorList(upload);
    for (int i = 0; i < list.size(); i++) {
      list.get(i).setLevelNum(Math.round(LEVEL_DEPTH[upload.getLevelNum()]));
    }
    return getDataTable(list);
  }

  /**
   * 进行文件上传
   * 如果是nc文件则把nc文件信息插入到数据表中
   *
   * @param file nc文件
   * @return
   */
  private AjaxResult uploadFile(Integer userId, String userName, MultipartFile[] file, Integer dataSetId, Integer memoryId, Integer ifPng) {
    try {
      List<Integer> resultFileIds = new ArrayList<>();
      String fileDir = sysMemoryDeviceService.selectSysMemoryDeviceById(memoryId).getSysMemoryDevice()
          + sysDataSetService.selectSysDataSetById(dataSetId).getDataSetDevice();
//      String fileDir = dataSetDir + "\\" + userId;
      int success = 0;
      for (MultipartFile multipartFile : file) {
        if (Objects.requireNonNull(multipartFile.getOriginalFilename()).contains(".nc")) {
          String times = StringUtils.getContinuityNum(Objects.requireNonNull(multipartFile.getOriginalFilename()), 8);
          String year = times.substring(0, 4);
          String month = times.substring(4, 6);
          String destFile = String.join(File.separator, fileDir, year, month);
          int i = ncUploadService.ncFileUpload(multipartFile, destFile);
          if (i == 1) {
            String fileName = FileUtils.getName(multipartFile.getOriginalFilename());
            String filePath = String.join(File.separator, destFile, fileName);
            Upload ncUploadFile = ncUploadService.getNcUploadFile(filePath);

//            User currentUser = ShiroUtils.getSysUser();
//            LoginUser loginUser = SecurityUtils.getLoginUser();
            Date nowTime = DateUtils.getNowDate();
            ncUploadFile.setUserId(userId);
            ncUploadFile.setUserName(userName);
            ncUploadFile.setFileArea("Global");
            ncUploadFile.setFileUploadTime(nowTime);
            ncUploadFile.setFileSize((int) (multipartFile.getSize() / (1024 * 1024) + 1));
            ncUploadFile.setFileViewTime(nowTime);
            ncUploadFile.setFileViewNum(0);
            ncUploadFile.setFileDownloadNum(0);
            ncUploadFile.setFileMemoryId(memoryId);
            ncUploadFile.setFileDataSetId(dataSetId);

            //生成png并将路径存储到数据库中
//            if (ifPng == 1) {
//              String pngPath = String.join(File.separator, null, year, month, fileName.split(".")[0] + ".png");
//              String outPngPath = fileDir + pngPath;
//              NetcdfFile ncFile =NetcdfFile.open(filePath);
//
//
//            }

            //  url只能在上传时获取
//            ncUploadFile.setFilePath("C"+StringUtils.substring(filPath,1));
            Date fileTime = DateUtils.dateTime("yyyyMMdd", times);
            ncUploadFile.setFileTime(fileTime);

            ncUploadFile.setFilePath(File.separator + String.join(File.separator, year, month, fileName));
            uploadService.insertUpload(ncUploadFile);


            resultFileIds.add(uploadService.selectNewInsert(null).getFileId());

          }
          success = success + i;
        } else {
//          multipartFile.transferTo(Paths.get(String.join(File.separator, applicationProperties.getDataDir(), multipartFile.getOriginalFilename())));

          if (!new File(fileDir).exists()) {
            new File(fileDir).mkdirs();
          }
          String[] fileSplit = multipartFile.getOriginalFilename().split("/");
          multipartFile.transferTo(new File(fileDir, fileSplit[fileSplit.length - 1]));
          success++;

          //记录存入数据库
          SysUploadFile sysUploadFile = new SysUploadFile();
          sysUploadFile.setUserId(userId);
          sysUploadFile.setUserName(userName);
          Date date = DateUtils.getNowDate();
          sysUploadFile.setFileTime(date);
//          sysUploadFile.setFileInfo(jobName);
          String[] split = (fileDir + fileSplit[fileSplit.length - 1]).split(":");
          sysUploadFile.setFilePath(split[split.length - 1]);

          sysUploadFileService.insertSysUploadFile(sysUploadFile);
        }
        logger.info("上传文件总路径为:" + String.join(File.separator, applicationProperties.getDataDir(), COPERNICUS));
      }
      if (success == file.length) {
        return AjaxResult.success(resultFileIds);

      } else {
        return AjaxResult.warn("部分数据未上传成功");
      }
    } catch (Exception e) {
      e.printStackTrace();
      logger.info("上传文件总路径为:" + String.join(File.separator, applicationProperties.getDataDir(), COPERNICUS));
      return AjaxResult.error("上传失败由于" + e.getMessage());
    }
  }

  /**
   * 单个文件预览
   */
  @ResponseBody
  @RequestMapping("/getImage")
  public AjaxResult getImage(HttpServletResponse response, Integer fileId) throws IOException {
    try {
      Upload uploadFile = uploadService.selectUploadByFileId(fileId);
      String filePath = getFilePath(uploadFile);
      if (!new File(filePath).exists()) {
        return AjaxResult.error("缩略图不存在，请重试");
      }
      response.setContentType("image/png;charset=utf-8");
      ServletOutputStream outputStream = response.getOutputStream();
      outputStream.write(Files.readAllBytes(Paths.get(filePath)));
      outputStream.flush();
      outputStream.close();
      Upload updateUpload = new Upload();
      updateUpload.setFileId(fileId);
      updateUpload.setFileViewNum(uploadFile.getFileViewNum() + 1);
      updateUpload.setFileViewTime(DateUtils.getNowDate());
      uploadService.updateUpload(updateUpload);

      return AjaxResult.success("预览成功");
    } catch (Exception e) {
      return AjaxResult.error(e.toString());
    }
  }

  /**
   * 海洋nc数据下载
   */
  @ResponseBody
  @RequestMapping("/downloadNcFile")
  public AjaxResult downloadNcFile(HttpServletResponse response, Integer fileId) {
    try {
      Upload uploadFile = uploadService.selectUploadByFileId(fileId);
      String filePath = getFilePath(uploadFile);
      if (!new File(filePath).exists()) {
        return AjaxResult.error("文件不存在，请重试");
      }
      File file = new File(filePath);

//      response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(uploadFile.getFilePath(), "UTF-8"));//文件下载
//      response.addHeader("Content-Disposition", "inline;filename=" + URLEncoder.encode(fileName,"UTF-8"));//文件预览
      response.setContentType("application/octet-stream");//文件
      response.setContentLength((int) file.length());
      response.addHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(uploadFile.getFilePath(), "UTF-8"));


      byte[] bytes = FileUtils.getFileByteArray(file);//使用FileUtil从filePath中去读取文件
      ServletOutputStream outputStream = response.getOutputStream();
      outputStream.write(bytes);//把文件的字节数写出去
      outputStream.flush();//刷新一下
      outputStream.close();//一定要关闭文件流


      Upload updateUpload = new Upload();
      updateUpload.setFileId(fileId);
      updateUpload.setFileDownloadNum(uploadFile.getFileDownloadNum() + 1);
      uploadService.updateUpload(updateUpload);

      return AjaxResult.success("文件下载成功");
    } catch (Exception e) {
      return AjaxResult.error(e.toString());
    }
  }

  /**
   * 获取磁盘目录及剩余空间
   *
   * @return
   */
  @ResponseBody
  @GetMapping("/getFileSystemView")
  public OUCAjaxResult getFileSystemView() {
    List<SysDiskSpace> fileSystemView = sysDataSetService.getFileSystemView();
    System.out.println("fileSystemView = " + fileSystemView);
    return OUCAjaxResult.ok(fileSystemView);
  }

  /**
   * 海洋数据统计
   */
  @ResponseBody
  @RequestMapping("/dataStatistics")
  public OUCAjaxResult dataStatistics() {
    Map<String, Integer> result = new HashMap<>();
    List<Upload> uploadList = uploadService.selectAllList();
    result.put("dataNum", uploadList.size());
    Integer dataSize = 0;
    Integer areaNum = 0;
    Integer saltNum = 0;
    Integer sshNum = 0;
    Integer tempNum = 0;
    Integer uvNum = 0;
    int[] year = new int[3000];
    for (Upload upload : uploadList) {
      if (upload.getFileSize() != null) {
        dataSize += upload.getFileSize();
      }
      if (upload.getFileArea() == "Global") {
        areaNum++;
      }
      if (upload.getVariableList().contains("ssh")) {
        sshNum++;
      }
      if (upload.getVariableList().contains("salt")) {
        saltNum++;
      }
      if (upload.getVariableList().contains("temp")) {
        tempNum++;
      }
      if (upload.getVariableList().contains("UV")) {
        uvNum++;
      }
      Date fileTime = upload.getFileTime();
      String yyyy = DateUtils.parseDateToStr("yyyy", fileTime);
      year[Integer.parseInt(yyyy)]++;

    }
    result.put("dataSize", dataSize);
    result.put("GlobalNum", areaNum);
    result.put("sshNum", sshNum);
    result.put("sstNum", tempNum);
    result.put("soNum", saltNum);
    result.put("curNum", uvNum);

    return OUCAjaxResult.ok(new Object[]{result, year});
  }

  private String getFilePath(Upload upload) {
    if (upload.getFileMemoryId() == null || upload.getFileDataSetId() == null || upload.getFilePath() == null) {
      return null;
    }
    return sysMemoryDeviceService.selectSysMemoryDeviceById(upload.getFileMemoryId()).getSysMemoryDevice()
        + sysDataSetService.selectSysDataSetById(upload.getFileDataSetId()).getDataSetDevice() + upload.getFilePath();
  }
}